package org.tomac.fix.example.fix42nordic;

import java.io.IOException;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.tomac.io.IIOPlexor;
import org.tomac.io.ITimerTask;
import org.tomac.io.fix.FixAcceptor;
import org.tomac.io.fix.FixURL;
import org.tomac.io.fix.IFixApplication;
import org.tomac.io.fix.IFixSession;
import org.tomac.io.fix.IFixURL;
import org.tomac.io.mina.MinaIOPlexorTest;
import org.tomac.protocol.fix.messaging.FixHeartbeat;
import org.tomac.protocol.fix.messaging.FixLogon;
import org.tomac.protocol.fix.messaging.FixLogout;
import org.tomac.protocol.fix.messaging.FixMessage;
import org.tomac.protocol.fix.messaging.FixMessageListener;
import org.tomac.protocol.fix.messaging.FixMessageListenerImpl;
import org.tomac.protocol.fix.messaging.FixNewOrderSingle;
import org.tomac.protocol.fix.messaging.FixReject;
import org.tomac.protocol.fix.messaging.FixResendRequest;
import org.tomac.protocol.fix.messaging.FixSequenceReset;
import org.tomac.protocol.fix.messaging.FixTestRequest;

public class FixServerMina extends FixMessageListenerImpl implements IFixApplication {

	private static Logger log = Logger.getLogger(FixServerMina.class.getSimpleName());

	FixMessageListenerReplicator replicator = new FixMessageListenerReplicator(this);

	IFixSession session;
	MinaIOPlexorTest plex;
	boolean forever = true;
	boolean isSendingOrders = false;
	final int RECONNECT_TIME = 1000;
	
	static public void main(String[] args) {

		if (args.length < 1) {
			System.out.println("Usage: FixClient <fix_url>");
			System.out.println("Example: FixClient fix42nordic://TOMAC:TE@127.0.0.1:1212?heartBtInt=60#initiator");
			return;
		}
		
		BasicConfigurator.configure();
		
		IFixURL url = new FixURL(args[0]); 

		IIOPlexor plex = new MinaIOPlexorTest();

		IFixApplication app = new FixServerMina();
			
		IFixSession acceptor = new FixAcceptor(plex, url, app);
			
		app.init(acceptor, plex);
			
	}


	@Override
	public void init(IFixSession session, IIOPlexor plex) {
		this.session = session;
		this.plex = (MinaIOPlexorTest)plex;
		try {

			session.connect();

		} catch (IOException e) {
			if (log.isDebugEnabled()) log.error(e.getMessage(), e);
			else log.error(e.getMessage());
		}
	}
	
	@Override
	public void onDisconnect() {
		log.info("Got disconnect");
		ReconnectTimerTask reconn = new ReconnectTimerTask(plex, session, RECONNECT_TIME);
		plex.scheduleTimer(reconn, RECONNECT_TIME);
	}

	@Override
	public void onConnect() {
		log.info("Got connect");
	}
	
	@Override
	public FixMessageListener getInboundFixMessageReplicator() {
		return replicator;
	}

	@Override
	public void onFixNewOrderSingle(FixNewOrderSingle msg) {
		msg.buf.flip();
		byte[] buf = new byte[msg.buf.limit()];
		msg.buf.slice().get(buf);
		if (log.isDebugEnabled()) log.debug("Bounce NewOrderSingle: " + new String(buf).replace("\1", "@"));
		session.send(msg);
	}
	
	private class FixMessageListenerReplicator extends FixMessageListenerImpl implements FixMessageListener {
		
		FixServerMina parent;
		
		public FixMessageListenerReplicator(FixServerMina fixApplicationTest) {
			parent = fixApplicationTest;
		}

		@Override
		public void onFixNewOrderSingle(FixNewOrderSingle msg) {
			session.onFixNewOrderSingle(msg); // increment InSeqNo
			parent.onFixNewOrderSingle(msg);
		}

		@Override
		public void onUnknownMessageType(FixMessage msg) {
			session.onUnknownMessageType(msg);
		}

		@Override
		public void onFixHeartbeat(FixHeartbeat msg) {
			session.onFixHeartbeat(msg);
			
		}

		@Override
		public void onFixLogon(FixLogon msg) {
			session.onFixLogon(msg);
			
		}

		@Override
		public void onFixLogout(FixLogout msg) {
			session.onFixLogout(msg);
			
		}

		@Override
		public void onFixReject(FixReject msg) {
			session.onFixReject(msg);
			
		}

		@Override
		public void onFixResendRequest(FixResendRequest msg) {
			session.onFixResendRequest(msg);
			
		}

		@Override
		public void onFixSequenceReset(FixSequenceReset msg) {
			session.onFixSequenceReset(msg);
			
		}

		@Override
		public void onFixTestRequest(FixTestRequest msg) {
			session.onFixTestRequest(msg);
			
		}
	}
	
	public class FixAcceptorTest extends org.tomac.io.fix.FixAcceptor {

		public FixAcceptorTest(IIOPlexor plex, IFixURL url, IFixApplication application) {
			super(plex, url, application);
		}

		@Override
		public void onFixNewOrderSingle(FixNewOrderSingle msg) {
			incrementInMsgSeqNum();
		}
		

	}	

	private class ReconnectTimerTask implements ITimerTask {
		IFixSession session;
		int previousTime;
		MinaIOPlexorTest plex;

		public ReconnectTimerTask(MinaIOPlexorTest plex, IFixSession session, int previousTime) {
			this.session = session;
			this.previousTime = previousTime;
			this.plex = plex;
		}

		@Override
		public void run() {
			try {
				session.connect();
			} catch (IOException e) {
				if (log.isDebugEnabled()) log.error(e.getMessage(), e);
				else log.error(e.getMessage());
				plex.scheduleTimer(this, previousTime * 2);
			}
		}
		
	}
	
}
